#include "../include/json/json.hpp"
#include "../include/LRUCache.h"
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstdlib>
#include <csignal>
#include <fcntl.h>

#define SERVER_IP "127.0.0.1"  // 服务器 IP 地址
#define SERVER_PORT 8888       // 服务器端口
int sock = -1;  // 全局变量，用于保存与服务器的连接

struct WebPageResp {
    int docId;
    std::string docTitle;
    std::string url;
    std::string docSummary;

    WebPageResp(int docId, std::string &docTitle, std::string &url, std::string docSummary);
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(WebPageResp, docId, docTitle, url, docSummary);

struct CliRequestMsg {
    std::string mesid;
    std::string content;
    int pageSize{};
    int pageNum{};

    CliRequestMsg(const string &mesid, const string &content, int pageSize, int pageNum) 
    : mesid(mesid)
    , content(content)
    , pageSize(pageSize)
    , pageNum(pageNum)
    {}
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CliRequestMsg, mesid, content, pageSize, pageNum);

bool sendRequest(std::string request);

std::string receiveResponse();

int webSearch(const std::string &keyword, int pageNum, int pageSize, int &totalRows)
{
    std::cout << "执行网页搜索逻辑，搜索关键词为：" << keyword << std::endl;
    // 在这里编写网页搜索的逻辑

    CliRequestMsg send = {"2", keyword, pageSize, pageNum};
    json sendJ = send;
    sendRequest(sendJ.dump());

    //std::cout << "接收数据"
    receiveResponse();
    //std::cout << receiveResponse() << std::endl;

    totalRows = 100;  // 假设总共有100行搜索结果（示例）
    return totalRows;
}

void keywordSearch(const std::string &keyword)
{
    std::cout << "执行关键词搜索逻辑，搜索关键词为：" << keyword << std::endl;

    CliRequestMsg send = {"1", keyword, 0, 0};
    json sendJ = send;
    sendRequest(sendJ.dump());
    receiveResponse();
}

void performWebSearch(const std::string &keyword)
{
    int pageNum = 1;  // 初始页数为1
    int pageSize = 10;  // 初始行数为10
    int totalRows = 0;
    int totalPages = webSearch(keyword, pageNum, pageSize, totalRows);
    int maxPages = (totalRows + pageSize - 1) / pageSize;  // 计算可进行的分页数

    std::cout << "当前分页参数为：页数 " << pageNum << "，行数 " << pageSize << std::endl;
    std::cout << "总行数：" << totalRows << std::endl;
    std::cout << "可进行的分页数：" << maxPages << std::endl;

    while (true) {
        std::string userInput;
        std::cout << "请输入命令（上一页：p，下一页：n，退出：q）：";
        std::cin >> userInput;

        if (userInput == "p") {
            if (pageNum > 1) {
                pageNum--;
                std::cout << "已切换到上一页，当前页数为：" << pageNum << std::endl;
                // 在这里根据新的页数执行网页搜索逻辑
            } else {
                std::cout << "已经是第一页，无法切换到上一页。" << std::endl;
            }
        } else if (userInput == "n") {
            if (pageNum < maxPages) {
                pageNum++;
                std::cout << "已切换到下一页，当前页数为：" << pageNum << std::endl;
                // 在这里根据新的页数执行网页搜索逻辑
            } else {
                std::cout << "已经到达最后一页，无法切换到下一页。" << std::endl;
            }
        } else if (userInput == "q") {
            break;
        } else {
            std::cout << "无效的命令，请重新输入。" << std::endl;
        }
    }
}

int searchLoop()
{
    std::cout << "打开了搜索服务" << std::endl;

    std::string userInput;
    while (true) {
        std::cout << "请输入命令（命令1：关键词搜索，命令2：网页搜索，退出请输入q）：";
        std::cin >> userInput;

        if (userInput == "1") {
            // 执行关键词搜索逻std::string keyword;
            std::string keyword;
            std::cout << "请输入要搜索的关键词：";
            std::cin >> keyword;
            keywordSearch(keyword);
        } else if (userInput == "2") {
            std::string keyword;
            std::cout << "请输入要搜索的网页关键词：";
            std::cin >> keyword;
            performWebSearch(keyword);
        } else if (userInput == "q") {
            break;
        } else {
            std::cout << "无效的命令，请重新输入。" << std::endl;
            continue;
        }

        std::cout << std::endl;
        std::cout << "是否继续搜索？（直接回车继续搜索，输入q退出）：";
        std::cin.ignore();  // 忽略输入缓冲区中的换行符
        std::getline(std::cin, userInput);
        if (userInput == "q") {
            break;
        }
    }

    return 0;
}


bool connectToServer()
{
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        std::cerr << "Failed to create socket." << std::endl;
        return false;
    }

    sockaddr_in serverAddr{};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(SERVER_PORT);
    if (inet_pton(AF_INET, SERVER_IP, &(serverAddr.sin_addr)) <= 0) {
        std::cerr << "Invalid server IP address." << std::endl;
        close(sock);
        return false;
    }

    if (connect(sock, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) == -1) {
        if (errno != EINPROGRESS) {
            std::cerr << "Failed to initiate connection." << std::endl;
            close(sock);
            return 1;
        }
    }

    return true;
}

bool sendRequest(std::string request)
{
    std::cout << "发送数据:\n" << request << std::endl;
    if (sock == -1) {
        std::cerr << "Not connected to the server." << std::endl;
        return false;
    }

    request += '\n';
    ssize_t bytesSent = send(sock, request.c_str(), request.length(), 0);

    return true;
}

int readn(char *buf, int len)
{
    int left = len;
    char *pstr = buf;
    int ret = 0;

    while(left > 0)
    {
        ret = read(sock, pstr, left);
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            perror("read error -1");
            return -1;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            pstr += ret;
            left -= ret;
        }
    }

    return len - left;
}

int readLine(char *buf, int len)
{
    int left = len - 1;
    char *pstr = buf;
    int ret = 0, total = 0;

    while(left > 0)
    {
        //MSG_PEEK不会将缓冲区中的数据进行清空,只会进行拷贝操作
        ret = recv(sock, pstr, left, MSG_PEEK);
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            perror("readLine error -1");
            return -1;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            for(int idx = 0; idx < ret; ++idx)
            {
                if(pstr[idx] == '\n')
                {
                    int sz = idx + 1;
                    readn(pstr, sz);
                    pstr += sz;
                    *pstr = '\0';//C风格字符串以'\0'结尾

                    return total + sz;
                }
            }

            readn(pstr, ret);//从内核态拷贝到用户态
            total += ret;
            pstr += ret;
            left -= ret;
        }
    }
    *pstr = '\0';

    return total - left;

}

std::string receiveResponse() {
    char buff[100000] = {0};
    readLine(buff, sizeof(buff));

    json jsonBuf = json::parse(buff);
    cout << std::setw(4) << jsonBuf << '\n';
    return buff;
}

std::string receiveResponse1()
{
    if (sock == -1) {
        std::cerr << "Not connected to the server." << std::endl;
        return "";
    }

    std::string response;
    char buffer[1024];
    memset(buffer, 0, sizeof(buffer));

    while (true) {
        int bytesRead = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if (bytesRead < 0) {
            std::cerr << "Failed to receive response from the server." << std::endl;
            close(sock);
            return "";
        } else if (bytesRead == 0) {
            // 读取完所有数据
            break;
        }

        response += buffer;
        memset(buffer, 0, sizeof(buffer));
    }

    std::cout << "接收数据:\n" << response << std::endl;
    return response;
}

void closeConnection()
{
    if (sock != -1) {
        close(sock);
        sock = -1;
    }
}

void handleExit(int signal)
{
    closeConnection();
    exit(0);
}

int main()
{
    if (!connectToServer()) {
        std::cerr << "Failed to connect to the server." << std::endl;
        return 1;
    }

    // 注册信号处理函数，捕捉程序关闭事件
    signal(SIGINT, handleExit);

    searchLoop();

    closeConnection();

    return 0;
}
